package research_aggregator;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

public class DeIdentifiedHealthRecord {
	private final String defaultPublicRecord = "<public><publicstat><height>0.0</height><weight>0.0</weight><age>0</age><gender /><race /><city /><state /></publicstat><medical><diagnosis><doctor /><diagnosis /><date /></diagnosis><treatment><type /><description /><comment /><date /></treatment><testresult><test /><result /><comment /><date /><performedby /></testresult></medical></public>";
	public Document publicRecord = null;
	public PublicHealthRecord publicRecordObject;
	public String patientId;
	public String identifier;

	public class PublicHealthRecord {
		public PublicStat publicStat;
		public MedicalRecord medical;

		public PublicHealthRecord() {
			publicStat = new PublicStat();
			medical = new MedicalRecord();
		}
	}

	public class PublicStat {
		public double height;
		public double weight;
		public int age;
		public String gender;
		public String race;
		public String city;
		public String state;

		public PublicStat() {
			height = 0.0;
			weight = 0.0;
			age = 0;
			gender = "";
			race = "";
			city = "";
			state = "";
		}
	}

	public class Diagnosis {
		public String date;
		public String diagnosis;

		public Diagnosis() {
			date = "";
			diagnosis = "";
		}
	}

	public class Treatment {
		public String type;
		public String description;
		public String comment;
		public String date;

		public Treatment() {
			type = "";
			description = "";
			comment = "";
			date = "";
		}
	}

	public class TestResult {
		public String test;
		public String result;
		public String comment;
		public String date;
		public String performedby;

		public TestResult() {
			test = "";
			result = "";
			comment = "";
			date = "";
			performedby = "";
		}
	}

	public class MedicalRecord {
		public Diagnosis diagnosis;
		public Treatment treatment;
		public TestResult testResult;

		public MedicalRecord() {
			diagnosis = new Diagnosis();
			treatment = new Treatment();
			testResult = new TestResult();
		}
	}

	public DeIdentifiedHealthRecord() {
		SAXBuilder builder = new SAXBuilder();
		try {
			publicRecord = builder.build(new ByteArrayInputStream(
					defaultPublicRecord.getBytes()));
		} catch (JDOMException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		buildRecordData();
	}

	public DeIdentifiedHealthRecord(String publicRecordXml) {
		SAXBuilder builder = new SAXBuilder();
		try {
			if (publicRecordXml != null) publicRecord = builder.build(new ByteArrayInputStream(publicRecordXml.getBytes()));
			else publicRecord = builder.build(new ByteArrayInputStream(defaultPublicRecord.getBytes()));

		} catch (JDOMException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		buildRecordData();
	}

	private void buildRecordData() {
		publicRecordObject = new PublicHealthRecord();

		Element root = publicRecord.getRootElement();
		Element publicStat = (Element) root.getChildren("publicstat").get(0);

		publicRecordObject.publicStat.city = insertString(publicStat ,"city");
		publicRecordObject.publicStat.state = insertString(publicStat ,"state");
		publicRecordObject.publicStat.gender = insertString(publicStat ,"gender");
		publicRecordObject.publicStat.race = insertString(publicStat ,"race");


		publicRecordObject.publicStat.weight = insertDouble(publicStat ,"weight");
		publicRecordObject.publicStat.height = insertDouble(publicStat ,"height");


		publicRecordObject.publicStat.age = insertInteger(publicStat ,"age");

		
		if (root.getChild("medical") != null) {
			Element diagnosis = (Element) root.getChild("medical").getChildren("diagnosis").get(0);
			if (diagnosis == null) publicRecordObject.medical.diagnosis = null;
			else {
				publicRecordObject.medical.diagnosis.date = diagnosis.getChild("date").getText();
				publicRecordObject.medical.diagnosis.diagnosis = diagnosis.getChild("diagnosis").getText();
			}

			Element treatment = (Element) root.getChild("medical").getChildren("treatment").get(0);
			if (treatment == null) publicRecordObject.medical.treatment = null;
			else {
				publicRecordObject.medical.treatment.type = treatment.getChild("type").getText();
				publicRecordObject.medical.treatment.description = treatment.getChild("description").getText();
				publicRecordObject.medical.treatment.comment = treatment.getChild("comment").getText();
				publicRecordObject.medical.treatment.date = treatment.getChild("date").getText();
			}

			Element testResult = (Element) root.getChild("medical").getChildren("testresult").get(0);
			if (testResult == null) publicRecordObject.medical.testResult = null;
			else {
				publicRecordObject.medical.testResult.test = testResult.getChild("test").getText();
				publicRecordObject.medical.testResult.result = testResult.getChild("result").getText();
				publicRecordObject.medical.testResult.comment = testResult.getChild("comment").getText();
				publicRecordObject.medical.testResult.date = testResult.getChild("date").getText();
				publicRecordObject.medical.testResult.performedby = testResult.getChild("performedby").getText();
			}
		}
		else publicRecordObject.medical = null;
	}

	public String toPublicXml() {
		XMLOutputter outputter = new XMLOutputter(Format.getRawFormat());
		return outputter.outputString(publicRecord).replaceAll("[\n\r]", "");
	}

	private String insertString(Element e, String itemname) {
		if (e.getChild(itemname) == null)
			return "";
		else
			return e.getChildText(itemname);
	}

	private Double insertDouble(Element e, String itemname) {
		if (e.getChild(itemname) == null)
			return -1.0;
		else
			return Double.valueOf(e.getChildText(itemname));
	}

	private int insertInteger(Element e, String itemname) {
		if (e.getChild(itemname) == null)
			return -1;
		else 
			return Integer.valueOf(e.getChildText(itemname));
	}

	public void print() {
		System.out.println("MEDICAL RECORD of an anonymous subject");
		if (publicRecordObject.publicStat.age >= 0) System.out.println("age : " + publicRecordObject.publicStat.age);
		if (publicRecordObject.publicStat.gender != null) System.out.println("gender : " + publicRecordObject.publicStat.gender);
		if (publicRecordObject.publicStat.weight >= 0) System.out.println("weight : " + publicRecordObject.publicStat.weight);
		if (publicRecordObject.publicStat.height >= 0) System.out.println("height : " + publicRecordObject.publicStat.height);
		if (publicRecordObject.publicStat.city != null) System.out.println("city : " + publicRecordObject.publicStat.city);
		if (publicRecordObject.publicStat.state != null) System.out.println("state : " + publicRecordObject.publicStat.state);

		if (publicRecordObject.medical != null) {
			System.out.println("medical is not null");
			System.out.println("");
			printDiagnosisHistory();
			System.out.println("");
			printTreatmentHistory();
			System.out.println("");
			printTestResultHistory();
			System.out.println("");
		}
	}


	private void printDiagnosisHistory() {
		@SuppressWarnings("unchecked")
		List<Element> list = publicRecord.getRootElement().getChild("medical")
		.getChildren("diagnosis");

		if (list.size() > 1) {
			for (int index = 0; index < (list.size() - 1) ; index++) {
				Element history = list.get(index);
				System.out.println("Diagnosis - modifier: "
						+ history.getAttributeValue("modifiedby"));
				System.out.println(" diagnosis: "
						+ history.getChildText("diagnosis"));
				System.out.println(" date: " + history.getChildText("date"));
			}
		} else
			System.out.println("no diagnosis made");
	}

	private void printTreatmentHistory() {
		@SuppressWarnings("unchecked")
		List<Element> list = publicRecord.getRootElement().getChild("medical")
		.getChildren("treatment");
		if (list.size() > 1) {
			for (int index = 0; index < (list.size() - 1) ; index++) {
				Element history = list.get(index);
				System.out.println("treatment - modifier: "
						+ history.getAttributeValue("modifiedby"));
				System.out.println(" type: " + history.getChildText("type"));
				System.out.println(" description: "
						+ history.getChildText("description"));
				System.out.println(" comment: "
						+ history.getChildText("comment"));
				System.out.println(" date: " + history.getChildText("date"));
			}
		} else
			System.out.println("no treatment");
	}

	private void printTestResultHistory() {
		@SuppressWarnings("unchecked")
		List<Element> list = publicRecord.getRootElement().getChild("medical")
		.getChildren("testresult");

		if (list.size() > 1) {
			for (int index = 0; index < (list.size() - 1) ; index++) {
				Element history = list.get(index);
				System.out.println("test result - modifier: "
						+ history.getAttributeValue("modifiedby"));
				System.out.println(" name: " + history.getChildText("test"));
				System.out
				.println(" result: " + history.getChildText("result"));
				System.out.println(" comment: "
						+ history.getChildText("comment"));
				System.out.println(" date: " + history.getChildText("type"));
				System.out.println(" performed by: "
						+ history.getChildText("performedby"));
			}
		} else
			System.out.println("no test result");
	}

	public String getId() {
		return patientId;
	}
}
